﻿

namespace Huirui.Cavan.Domain.MainBoundedContext.SystemModule
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Huirui.Cavan.Domain.Seedwork;
    using Huirui.Cavan.Core.Extension;
    using Huirui.Cavan.Domain.MainBoundedContext.SalesModule;
    using Huirui.Cavan.Domain.MainBoundedContext.PurchaseModule;
    using Huirui.Cavan.Core.Cryptography;

    public class Administrator
    {
        private Employee _employee;

        public Administrator(Employee employee)
        {
            this._employee = employee;
        }

        public BoolGenericResult<Account> AddAccount(string id, string name, string currency, SystemIdentifier.AccountType type, SystemIdentifier.AccountStatus status)
        {
            BoolGenericResult<Account> result = new BoolGenericResult<Account>();

            Account account = SystemModuleFactory.CreateAccount(id, name, currency, type, status, this._employee.UserAccount.Id, this._employee.Corporation);

            result.Object = account;

            return result;
        }

        public BoolGenericResult<Account> UpdateAccount(Account oldAccount, string name, string currency,decimal amount, SystemIdentifier.AccountType type, SystemIdentifier.AccountStatus status)
        {
            BoolGenericResult<Account> result = new BoolGenericResult<Account>();

            oldAccount.Name = name;
            oldAccount.Currency = currency;
            oldAccount.Type = type;
            oldAccount.Status = status;
            oldAccount.InitialAmount = amount;
            result.Object = oldAccount;

            return result;
        }

        public EditBaseCodeRule AddBaseCodeRule(string name, SystemIdentifier.BaseCodeRuleType type, string prefix, bool isDefault, int serialNumberNumber,
            int serialNumberStart, string example)
        {
            EditBaseCodeRule result = new EditBaseCodeRule();
            BaseCodeRule baseCodeRule = SystemModuleFactory.CreateBaseCodeRule(name, type, prefix, isDefault, serialNumberNumber, 1, example,
                this._employee.UserAccount.Id, this._employee.Corporation);
            CodeRuleProperty codeRuleProperty = SystemModuleFactory.CreateCodeRuleProperty(baseCodeRule.Id, SystemIdentifier.CodeRuleType.Base.GetHashCode(), serialNumberStart - 1, this._employee.UserAccount.Id);
            result.Object = baseCodeRule;
            result.CodeRuleProperty = codeRuleProperty;

            return result;
        }

        public EditBaseCodeRule UpdateBaseCodeRule(BaseCodeRule oldBaseCodeRule, CodeRuleProperty oldCodeRuleProperty, string name, SystemIdentifier.BaseCodeRuleType type, string prefix, bool isDefault, int serialNumberNumber,
            int serialNumberStart, string example)
        {
            EditBaseCodeRule result = new EditBaseCodeRule();
            //if (serialNumberStart < oldCodeRuleProperty.Max)
            //{
            //    result.IsSuccess = false;
            //    result.Messages.Add("起始号需大于" + oldCodeRuleProperty.Max.ToString());
            //    return result;
            //}
            oldBaseCodeRule.Name = name;
            oldBaseCodeRule.Type = type;
            oldBaseCodeRule.Prefix = prefix;
            oldBaseCodeRule.IsDefault = isDefault;
            oldBaseCodeRule.SerialNumberNumber = serialNumberNumber;
            //oldBaseCodeRule.SerialNumberStart = serialNumberStart;
            oldBaseCodeRule.Example = example;

            result.Object = oldBaseCodeRule;

            oldCodeRuleProperty.Max = oldCodeRuleProperty.Max < serialNumberStart ? serialNumberStart : oldCodeRuleProperty.Max;
            result.CodeRuleProperty = oldCodeRuleProperty;

            return result;
        }

        public EditReceiptCodeRule AddReceiptCodeRule(string name, SystemIdentifier.ReceiptCodeRuleType type, string prefix, bool isDefault, int serialNumberNumber,
    int serialNumberStart, SystemIdentifier.CodePattern pattern, int yearNumber, string example)
        {
            EditReceiptCodeRule result = new EditReceiptCodeRule();
            ReceiptCodeRule receiptCodeRule = SystemModuleFactory.CreateReceiptCodeRule(name, type, prefix, pattern, isDefault, serialNumberNumber, 1, yearNumber, example,
                this._employee.UserAccount.Id, this._employee.Corporation);
            CodeRuleProperty codeRuleProperty = SystemModuleFactory.CreateCodeRuleProperty(receiptCodeRule.Id, SystemIdentifier.CodeRuleType.Receipt.GetHashCode(), serialNumberStart - 1, this._employee.UserAccount.Id);
            result.Object = receiptCodeRule;
            result.CodeRuleProperty = codeRuleProperty;

            return result;
        }

        public EditReceiptCodeRule UpdateReceiptCodeRule(ReceiptCodeRule oldReceiptCodeRule, CodeRuleProperty oldCodeRuleProperty, string name, SystemIdentifier.ReceiptCodeRuleType type, string prefix, bool isDefault, int serialNumberNumber,
    int serialNumberStart, SystemIdentifier.CodePattern pattern, int yearNumber, string example)
        {
            EditReceiptCodeRule result = new EditReceiptCodeRule();
            oldReceiptCodeRule.Name = name;
            oldReceiptCodeRule.Type = type;
            oldReceiptCodeRule.Prefix = prefix;
            oldReceiptCodeRule.IsDefault = isDefault;
            oldReceiptCodeRule.SerialNumberNumber = serialNumberNumber;
            //oldReceiptCodeRule.SerialNumberStart = serialNumberStart;
            oldReceiptCodeRule.Pattern = pattern;
            oldReceiptCodeRule.YearNumber = yearNumber;
            oldReceiptCodeRule.Example = example;

            result.Object = oldReceiptCodeRule;

            oldCodeRuleProperty.Max = oldCodeRuleProperty.Max < serialNumberStart ? serialNumberStart : oldCodeRuleProperty.Max;
            result.CodeRuleProperty = oldCodeRuleProperty;

            return result;
        }

        public BoolGenericResult<Corporation> AddCorporation(string code, string name, IndustryType industry, string englishName, int maxUser, string contact, string website, string mobile, string telephone, string fax, string email, Area area, string address, string addressEnglish, string deliveryAddress2, string deliveryAddress3, string deliveryAddress1, string taxIdentificationNumber, string bank, string bankAccount)
        {
            BoolGenericResult<Corporation> result = new BoolGenericResult<Corporation>();

            Corporation corporation = SystemModuleFactory.CreateCorporation(code, name, industry, englishName, maxUser, contact, website, mobile, telephone, fax, email, area, address, addressEnglish, deliveryAddress2, deliveryAddress3, deliveryAddress1, taxIdentificationNumber, bank, bankAccount, this._employee.UserAccount.Id);
            result.Object = corporation;
            return result;
        }

        public BoolGenericResult<Corporation> UpdateCorporation(Corporation oldCorporation, string name, IndustryType industry, string englishName,
            int maxUser, string contact, string website, string mobile, string telephone, string fax, string email, Area area, string address,
            string addressEnglish, string deliveryAddress2, string deliveryAddress3, string deliveryAddress1, string taxIdentificationNumber,
            string bank, string bankAccount)
        {
            BoolGenericResult<Corporation> result = new BoolGenericResult<Corporation>();
            oldCorporation.Name = name;
            oldCorporation.Industry = industry;
            oldCorporation.EnglishName = englishName;
            oldCorporation.MaxUser = maxUser;
            oldCorporation.Contact = contact;
            oldCorporation.Website = website;
            oldCorporation.Mobile = mobile;
            oldCorporation.Telephone = telephone;
            oldCorporation.Fax = fax;
            oldCorporation.Email = email;
            oldCorporation.Area = area;
            oldCorporation.Address = address;
            oldCorporation.AddressEnglish = addressEnglish;
            oldCorporation.DeliveryAddress2 = deliveryAddress2;
            oldCorporation.DeliveryAddress1 = deliveryAddress1;
            oldCorporation.DeliveryAddress3 = deliveryAddress3;
            oldCorporation.TaxIdentificationNumber = taxIdentificationNumber;
            oldCorporation.Bank = bank;
            oldCorporation.BankAccount = bankAccount;
            oldCorporation.EditUser = this._employee.UserAccount.Id;
            oldCorporation.ModifyDate = DateTime.Now;
            result.Object = oldCorporation;
            return result;
        }

        public BoolGenericResult<SystemConfig> AddSystemConfig(SystemIdentifier.SystemConfigType type, string item, string value, SystemIdentifier.DataType dataType, string description, string remark)
        {
            BoolGenericResult<SystemConfig> result = new BoolGenericResult<SystemConfig>();

            SystemConfig systemConfig = SystemModuleFactory.CreateSystemConfig(type, item, value, dataType, description, remark, this._employee.UserAccount.Id, this._employee.Corporation);

            result.Object = systemConfig;

            return result;
        }

        public BoolGenericResult<SystemConfig> UpdateSystemConfig(SystemConfig oldSystemConfig, string value, string remark)
        {
            BoolGenericResult<SystemConfig> result = new BoolGenericResult<SystemConfig>();

            oldSystemConfig.Value = value;
            //oldSystemConfig.Remark = remark;

            result.Object = oldSystemConfig;

            return result;
        }

        public BoolGenericResult<Department> AddDepartment(string code, string name, string remark, string superiorDepartment)
        {
            BoolGenericResult<Department> result = new BoolGenericResult<Department>();
            Department department = SystemModuleFactory.CreateDepartment(code, name, remark, superiorDepartment, this._employee.UserAccount.Id, this._employee.Corporation);
            result.Object = department;

            return result;
        }

        public BoolGenericResult<Department> UpdateDepartment(Department oldDepartment, string name, string remark, string superiorDepartment)
        {
            BoolGenericResult<Department> result = new BoolGenericResult<Department>();
            oldDepartment.Name = name;
            oldDepartment.Remark = remark;
            oldDepartment.ModifyDate = DateTime.Now;
            oldDepartment.EditUser = this._employee.UserAccount.Id;
            oldDepartment.SuperiorDepartment = superiorDepartment;
            result.Object = oldDepartment;

            return result;
        }

        public BoolGenericResult<Employee> AddEmployee(string code, string name, Job job, decimal? commissionRate, SystemIdentifier.Sex sex, DateTime? birthday, string email, string mobile, bool sMSQueryEnabled, string remark, string managerEmployeeCode, int editUser, Department department, UserAccount userAccount)
        {
            BoolGenericResult<Employee> result = new BoolGenericResult<Employee>();
            Employee employee = SystemModuleFactory.CreateEmployee(code, name, job, commissionRate, sex, birthday, email, mobile, sMSQueryEnabled, remark, managerEmployeeCode, editUser, this._employee.Corporation, department, userAccount);
            result.Object = employee;
            return result;
        }

        public BoolGenericResult<Employee> UpdateEmployee(Employee oldEmployee, string name, Job job, decimal? commissionRate, SystemIdentifier.Sex sex, DateTime? birthday, string email, string mobile, bool sMSQueryEnabled, string remark, int editUser, Department department)
        {
            BoolGenericResult<Employee> result = new BoolGenericResult<Employee>();
            oldEmployee.Name = name;
            oldEmployee.Job = job;
            oldEmployee.CommissionRate = commissionRate;
            oldEmployee.Sex = sex;
            oldEmployee.Birthday = birthday;
            oldEmployee.Email = email;
            oldEmployee.Mobile = mobile;
            oldEmployee.SMSQueryEnabled = sMSQueryEnabled;
            oldEmployee.Remark = remark;
            oldEmployee.EditUser = editUser;
            oldEmployee.Department = department;
            result.Object = oldEmployee;
            return result;
        }

        public BoolGenericResult<Currency> AddCurrency(string id, string name, decimal rate, bool isLocal)
        {
            BoolGenericResult<Currency> result = new BoolGenericResult<Currency>();

            Currency currency = SystemModuleFactory.CreateCurrency(id, name, rate, isLocal, this._employee.UserAccount.Id, this._employee.Corporation);

            result.Object = currency;

            return result;
        }

        public BoolGenericResult<Currency> UpdateCurrency(Currency oldCurrency, string name, decimal rate, bool isLocal)
        {
            BoolGenericResult<Currency> result = new BoolGenericResult<Currency>();

            oldCurrency.Name = name;
            oldCurrency.Rate = rate;
            oldCurrency.IsLocal = isLocal;

            result.Object = oldCurrency;

            return result;
        }

        public BoolGenericResult<Receivables> AddCustomerInitialBalance(DateTime initialDate, SalesIdentifier.ReceivablesType type, decimal amount, string currency, decimal currencyRate, Customer customer)
        {
            BoolGenericResult<Receivables> result = new BoolGenericResult<Receivables>();

            Receivables receivables = SalesModuleFactory.CreateReceivables(initialDate, currency, currencyRate, string.Empty,
               0, null, 0, DateTime.MaxValue, amount, type, string.Empty, initialDate, DateTime.Now, this._employee.UserAccount.Id,
               this._employee.Corporation, customer, this._employee, null);
            result.Object = receivables;

            return result;
        }

        public BoolGenericResult<UnPay> AddSupplierInitialBalance(DateTime initialDate, PurchaseIdentifier.UnPayType type, decimal amount, string currency, decimal currencyRate, Supplier supplier)
        {
            BoolGenericResult<UnPay> result = new BoolGenericResult<UnPay>();

            UnPay unPay = PurchaseModuleFactory.CreateUnPay(string.Empty, type, 0, amount, amount, SystemIdentifier.PayType.Cash, PurchaseIdentifier.PayCondition.None,
                null, null, currency, currencyRate, DateTime.Now, DateTime.Now, this._employee.UserAccount.Id, this._employee.Corporation, supplier);
            result.Object = unPay;

            return result;
        }

        public BoolGenericResult<Job> AddJob(string name, string remark)
        {
            BoolGenericResult<Job> result = new BoolGenericResult<Job>();

            Job job = SystemModuleFactory.CreateJob(name, remark, this._employee.UserAccount.Id, this._employee.Corporation);
            result.Object = job;

            return result;
        }

        public BoolGenericResult<UserAccount> AddUserAccount(string name, string password, Employee employee, bool isLocked)
        {
            BoolGenericResult<UserAccount> result = new BoolGenericResult<UserAccount>();
            Role role = SystemModuleFactory.CreateRole(name, "", true, DateTime.Now, this._employee.UserAccount.Id);
            UserAccount userAccount = SystemModuleFactory.CreateUserAccount(name, password, string.Empty, DateTime.Now, isLocked, false, 0, role, DateTime.Now, this._employee.UserAccount.Id, employee);
            result.Object = userAccount;

            return result;
        }

        public BoolGenericResult<UserAccount> UpdateUserAccount(UserAccount oldUserAccount, string name, string password, bool isLocked)
        {
            BoolGenericResult<UserAccount> result = new BoolGenericResult<UserAccount>();
            oldUserAccount.Name = name;
            oldUserAccount.Password = Crypto.Encrypt(password);
            oldUserAccount.IsLocked = isLocked;

            result.Object = oldUserAccount;

            return result;
        }

        public BoolGenericResult<UserAccount> AddActionToUserAccount(UserAccount userAccount, IList<SysController> controllers, IList<SysAction> actions)
        {
            if (userAccount.Role.IsNotNull())
            {
                IList<SysAction> addedSysActions = new List<SysAction>();
                foreach (SysAction newSysAction in actions)
                {
                    if (!userAccount.Role.Actions.Any(sa => sa.Id == newSysAction.Id))
                    {
                        addedSysActions.Add(newSysAction);
                    }
                }

                IList<SysAction> deletedSysActions = new List<SysAction>();
                foreach (SysAction oldSysAction in userAccount.Role.Actions)
                {
                    if (!actions.Any(sa => sa.Id == oldSysAction.Id))
                    {
                        deletedSysActions.Add(oldSysAction);
                    }
                }

                foreach (SysAction addedSysAction in addedSysActions)
                {
                    userAccount.Role.Actions.Add(addedSysAction);
                }
                foreach (SysAction deletedSysAction in deletedSysActions)
                {
                    userAccount.Role.Actions.Remove(deletedSysAction);
                }

                IList<SysController> permissionControllers = new List<SysController>();
                foreach (SysAction action in userAccount.Role.Actions)
                {
                    if (!userAccount.Role.Controllers.Any(c => c.Id == action.Controller.Id))
                    {
                        userAccount.Role.Controllers.Add(action.Controller);
                    }
                    if (!permissionControllers.Any(c => c.Id == action.Controller.Id))
                    {
                        permissionControllers.Add(action.Controller);
                    }
                }
                IList<SysController> deletedControllers = new List<SysController>();
                foreach (SysController controller in userAccount.Role.Controllers)
                {
                    if (!permissionControllers.Any(c => c.Id == controller.Id))
                    {
                        deletedControllers.Add(controller);
                    }
                }
                foreach (SysController controller in deletedControllers)
                {
                    userAccount.Role.Controllers.Remove(controller);
                }
            }
            else
            {
                userAccount.Role = new Role() { Name = userAccount.Name, IsUseDenied = true };
                foreach (SysAction action in actions)
                {
                    userAccount.Role.Actions.Add(action);
                    if (!userAccount.Role.Controllers.Any(c => c.Id == action.Controller.Id))
                    {
                        userAccount.Role.Controllers.Add(action.Controller);
                    }
                }
            }

            BoolGenericResult<UserAccount> result = new BoolGenericResult<UserAccount>();
            result.Object = userAccount;

            return result;
        }
    }
}
